﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Disposables;
using System.Linq;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Data;
using SoftSource.Common;
using SoftSource.Timecard.ViewModelInterfaces;
using SoftSource.Timecard.Web.Data;

namespace SoftSource.Timecard.ViewModels
{
    public sealed class InvoicingViewModel : IInvoicingViewModel
    {
        #region Fields
        private CompositeDisposable compositeDisposable;
        #endregion Fields

        public InvoicingViewModel()
        {
            this.compositeDisposable = new CompositeDisposable();
        }

        #region IInvoicingViewModelConsume Members

        private PagedCollectionView projects;
        public PagedCollectionView Projects
        {
            get { return this.projects; }
            private set
            {
                this.projects = value;
                this.projects.SortDescriptions.Add(new SortDescription(
                    ObjectReflection.GetPropertyName<InvoicingProject>(p => p.Name),
                    ListSortDirection.Ascending));
                this.projects.MoveCurrentToFirst();
                this.PropertyChanged.Notify(() => this.Projects);
            }
        }

        public Func<int, IObservable<string>> MarkProjectAsBilled
        {
            get
            {
                return (projectID) =>
                    {
                        var project = this.ProjectSource.SingleOrDefault(p => p.ProjectID == projectID);
                        
                        if (project != null && project.BilledAsOf.HasValue)
                        {
                            return this.MarkProjectAsBilledService(projectID, project.BilledAsOf.Value)
                                .Select(entries =>
                                    {
                                        int count = entries.Count();
                                        string message = "Save was successful";
                                        if (count > 0)
                                            message = string.Format("{0} entries where not approved prior to invoicing.", count);
                                        return message;
                                    });
                        }

                        return Observable.Return("Unable to save billing date.");
                    };
            }
        }

        public Func<int, Action, UIElement> CreateProjectEditor { get; set; }
        public IObservable<Unit> Load { get; set; }

        #endregion

        #region IInvoicingViewModelService Members

        private IEnumerable<InvoicingProject> projectSource;
        public IEnumerable<InvoicingProject> ProjectSource
        {
            get { return this.projectSource; }
            set
            {
                this.projectSource = value;
                this.Projects = new PagedCollectionView(this.projectSource);
            }
        }

        public Func<int, DateTime, IObservable<IEnumerable<EntryLog>>> MarkProjectAsBilledService { get; set; }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.compositeDisposable.Dispose();
            GC.SuppressFinalize(this);
        }

        #endregion

        ~InvoicingViewModel()
        {
            this.Dispose();
        }
    }
}
